package com.mingqijia.gassafety.authority.dal.provider;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mingqijia.gassafety.authority.api.resp.config.DivisionLiteRespDTO;
import com.mingqijia.gassafety.authority.dal.command.QueryDivisionCommand;
import com.mingqijia.gassafety.authority.dal.handler.DivisionTranslator;
import com.mingqijia.gassafety.db.entity.auth.DivisionEntry;
import com.mingqijia.gassafety.db.mapper.auth.DivisionMapper;
import com.mingqijia.gassafety.shared.constant.Constants;
import com.mingqijia.gassafety.shared.cqrs.QueryHandler;
import com.mingqijia.gassafety.shared.enums.YesNoEnum;
import com.mingqijia.gassafety.shared.handler.GlobalAuthenticationException;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 参数数据库查询操作类（Qu-Query）
 * @author Damon S.
 * @version v1.0.1
 * @date 2020年01月20日 15:58
 */
@Component
@RequiredArgsConstructor
public class DivisionProvider extends ServiceImpl<DivisionMapper, DivisionEntry> implements QueryHandler<DivisionEntry> {

    private final DivisionTranslator translator;


    public List<DivisionEntry> getDivision(String parent) {
        QueryWrapper<DivisionEntry> queryClause = new QueryWrapper<>();
        queryClause.lambda().eq(DivisionEntry::getParentId, parent);
        return this.list(queryClause);
    }

    public Page<DivisionEntry> find(QueryDivisionCommand command) {
        LambdaQueryWrapper<DivisionEntry> queryClause = new LambdaQueryWrapper<>();
        Optional.ofNullable(command.getParentId()).ifPresent(
                parent -> queryClause.eq(DivisionEntry::getParentId, parent)
        );
        Optional.ofNullable(command.getName()).ifPresent(
                name -> queryClause.like(DivisionEntry::getName, name)
        );
        Optional.ofNullable(command.getLevel()).ifPresent(
                level -> queryClause.eq(DivisionEntry::getLevel, level)
        );
        Optional.ofNullable(command.getState()).ifPresent(
                state -> queryClause.eq(DivisionEntry::getState, state.getCode())
        );
        queryClause.eq(DivisionEntry::getIsDeleted, YesNoEnum.N.getCode());
        return this.page(createPage(command), queryClause);
    }

    @Cacheable(value = Constants.CACHE_KEY_CONFIGURE, key = "'divisions'")
    public List<DivisionLiteRespDTO> listDivisionHierarchy() {
        List<DivisionLiteRespDTO> divisions = translator.toRespDTO(list());
        // 现获取省级行政单位
        List<DivisionLiteRespDTO> provinces = divisions.stream().filter(
                item -> Objects.equals(item.getParentId(), Constants.STR_ONE)
        ).collect(Collectors.toList());
        // 递归构建行政区划层级结构
        for (DivisionLiteRespDTO resp : provinces) {
            this.buildDivisionHierarchy(divisions, resp);
        }
        return provinces;
    }

    private void buildDivisionHierarchy(List<DivisionLiteRespDTO> sources,
                                        DivisionLiteRespDTO target) {
        target.setChildren(sources.stream().filter(
                item -> Objects.equals(item.getParentId(), target.getId())
        ).collect(Collectors.toList()));
        if (CollectionUtils.isEmpty(target.getChildren())) {
            return;
        }
        for (DivisionLiteRespDTO resp : target.getChildren()) {
            this.buildDivisionHierarchy(sources, resp);
        }
    }
}
